package com.ccp.dev.core.util;

import org.apache.commons.beanutils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.PropertyDescriptor;
import java.util.*;

import static org.springframework.util.ReflectionUtils.handleReflectionException;


/**
 * BeanUtils的等价类，只是将check exception改为uncheck exception
 *
 * @author badqiu
 */
public class BeanUtils {

    private static Logger logger= LoggerFactory.getLogger(BeanUtils.class);
    /**
     * BeanUtil类型转换器
     */
    public static ConvertUtilsBean convertUtilsBean = new ConvertUtilsBean();

    private static BeanUtilsBean beanUtilsBean = new BeanUtilsBean(convertUtilsBean, new PropertyUtilsBean());

    /**
     * 可以用于判断 Map,Collection,String,Array,Long是否为空
     *
     * @param o java.lang.Object.
     * @return boolean.
     */
    @SuppressWarnings("unused")
    public static boolean isEmpty(Object o) {
        if (o == null) {
            return true;
        }
        if (o instanceof String) {
            if (((String) o).trim().length() == 0) {
                return true;
            }
        } else if (o instanceof Collection) {
            if (((Collection) o).isEmpty()) {
                return true;
            }
        } else if (o.getClass().isArray()) {
            if (((Object[]) o).length == 0) {
                return true;
            }
        } else if (o instanceof Map) {
            if (((Map) o).isEmpty()) {
                return true;
            }
        }


        return false;

    }

    /**
     * 判断对象是否为空。
     * o:为null 返沪true。
     * 如果为集合，判断集合大小是否为0 为0则返回true
     * Double，Float,Long,Short,Integer 为0也表示为空。
     *
     * @param o Object对象
     * @return boolean
     */
    public static boolean isZeroEmpty(Object o) {
        if (o == null) {
            return true;
        }
        if (o instanceof String) {
            if (((String) o).trim().length() == 0) {
                return true;
            }
        } else if (o instanceof Collection) {
            if (((Collection) o).isEmpty()) {
                return true;
            }
        } else if (o.getClass().isArray()) {
            if (((Object[]) o).length == 0) {
                return true;
            }
        } else if (o instanceof Map) {
            if (((Map) o).isEmpty()) {
                return true;
            }
        } else if (o instanceof Double) {
            Double lEmpty = 0.0;
            if (o == lEmpty) {
                return true;
            }
        } else if (o instanceof Float) {
            Float lEmpty = 0f;
            if (o == lEmpty) {
                return true;
            }
        } else if (o instanceof Long) {
            Long lEmpty = 0L;
            if (o == lEmpty) {
                return true;
            }
        } else if (o instanceof Short) {
            Short sEmpty = 0;
            if (o == sEmpty) {
                return true;
            }
        } else if (o instanceof Integer) {
            Integer sEmpty = 0;
            if (o == sEmpty) {
                return true;
            }
        }

        return false;

    }


    /**
     * 可以用于判断 Map,Collection,String,Array是否不为空
     *
     * @param o Object对象
     * @return boolean
     */
    public static boolean isNotEmpty(Object o) {
        return !isEmpty(o);
    }

    public static boolean isNotEmpty(Long o) {
        return !isEmpty(o);
    }

    /**
     * 判断对象不为空。
     * 如果为0表示为空。
     *
     * @param o Object对象
     * @return boolean
     */
    public static boolean isNotIncZeroEmpty(Object o) {
        return !isZeroEmpty(o);
    }


    /**
     * 判断是否为数字
     *
     * @param o Object对象
     * @return boolean
     */
    public static boolean isNumber(Object o) {
        if (o == null) {
            return false;
        }
        if (o instanceof Number) {
            return true;
        }
        if (o instanceof String) {
            try {
                Double.parseDouble((String) o);
                return true;
            } catch (NumberFormatException e) {
                return false;
            }
        }
        return false;
    }


    /**
     * 根据指定的类名判定指定的类是否存在。
     *
     * @param className 类名
     * @return boolean
     */
    public static boolean validClass(String className) {
        try {
            Class.forName(className);
            return true;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }

    /**
     * 判定类是否继承自父类
     *
     * @param cls         子类
     * @param parentClass 父类
     * @return boolean
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static boolean isInherit(Class cls, Class parentClass) {
        return parentClass.isAssignableFrom(cls);
    }


    /**
     * 将字符串数据按照指定的类型进行转换。
     *
     * @param typeName 实际的数据类型
     * @param value    字符串值。
     * @return Object
     */
    public static Object convertByActType(String typeName, String value) {
        Object o = null;
        if ("int".equals(typeName)) {
            o = Integer.parseInt(value);
        } else if ("short".equals(typeName)) {
            o = Short.parseShort(value);
        } else if ("long".equals(typeName)) {
            o = Long.parseLong(value);
        } else if ("float".equals(typeName)) {
            o = Float.parseFloat(value);
        } else if ("double".equals(typeName)) {
            o = Double.parseDouble(value);
        } else if ("boolean".equals(typeName)) {
            o = Boolean.parseBoolean(value);
        } else if ("java.lang.String".equals(typeName)) {
            o = value;
        } else {
            o = value;
        }
        return o;
    }

    public static void setProperty(Object bean, String name, Object value) {
        try {
            beanUtilsBean.setProperty(bean, name, value);
        } catch (Exception e) {
            handleReflectionException(e);
        }
    }

    /**
     * 功能描述:map转对象
     *
     * @param:map 要转换的对象
     * @param:beanClass  目标类型
     * @return:
     * @auther: dfz
     * @date: 2019/5/23 17:21
     */

    public static Object mapToObject(Map<String, Object> map, Class<?> beanClass) throws Exception {
        if (map == null) {
            return null;
        }
        Object obj = beanClass.newInstance();
        org.apache.commons.beanutils.BeanUtils.populate(obj, map);
        return obj;
    }

    /**
     * 拷贝一个bean中的非空属性于另一个bean中
     *
     * @param dest
     * @param orig
     * @throws IllegalAccessException
     */
    public static void copyNotNullProperties(Object dest, Object orig){

        // Validate existence of the specified beans
        if (dest == null) {
            logger.error("No destination bean specified");
            return;
        }
        if (orig == null) {
            logger.error("No origin bean specified");
            return;
        }

        try{
            // Copy the properties, converting as necessary
            if (orig instanceof DynaBean) {
                DynaProperty[] origDescriptors = ((DynaBean) orig).getDynaClass()
                        .getDynaProperties();
                for (int i = 0; i < origDescriptors.length; i++) {
                    String name = origDescriptors[i].getName();
                    if (beanUtilsBean.getPropertyUtils().isReadable(orig, name)
                            && beanUtilsBean.getPropertyUtils().isWriteable(dest, name)) {
                        Object value = ((DynaBean) orig).get(name);
                        beanUtilsBean.copyProperty(dest, name, value);
                    }
                }
            } else if (orig instanceof Map) {
                Iterator entries = ((Map) orig).entrySet().iterator();
                while (entries.hasNext()) {
                    Map.Entry entry = (Map.Entry) entries.next();
                    String name = (String) entry.getKey();
                    if (beanUtilsBean.getPropertyUtils().isWriteable(dest, name)) {
                        beanUtilsBean.copyProperty(dest, name, entry.getValue());
                    }
                }
            } else /* if (orig is a standard JavaBean) */{
                PropertyDescriptor[] origDescriptors = beanUtilsBean.getPropertyUtils()
                        .getPropertyDescriptors(orig);
                for (int i = 0; i < origDescriptors.length; i++) {
                    String name = origDescriptors[i].getName();
                    if ("class".equals(name)) {
                        continue; // No point in trying to set an object's class
                    }
                    if (beanUtilsBean.getPropertyUtils().isReadable(orig, name)
                            && beanUtilsBean.getPropertyUtils().isWriteable(dest, name)) {
                        try {
                            Object value = beanUtilsBean.getPropertyUtils().getSimpleProperty(orig, name);
                            if (value != null) {
                                beanUtilsBean.copyProperty(dest, name, value);
                            }
                        } catch (NoSuchMethodException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }catch(Exception ex){
            handleReflectionException(ex);
        }

    }


}
